#include "estructuras.h"
#include <time.h>

/* produce cajas para eviar a armado */

int main(int argc, char *argv[])
{
	srand(time(NULL));
	char mensaje[120];
	m_kanbanproduccion msg_kproduccion;
	m_kanbanentreprocesos msg_kprocesos;
	m_kanbanproveedor msg_kproveedor;
	m_kanbancompras msg_kcompras;
	t_stock stock_caja;

	int producidos, fentregar, temprcv;

	int colaE, colaI;
	key_t clave_colaE, clave_colaI;

	clave_colaE = ftok(DIRECTORIO, COLA_EXTERNA);
	clave_colaI = ftok(DIRECTORIO, COLA_INTERNA);

	if ( (colaE = msgget(clave_colaE, 0666)) < 0 )				/* Obtengo el ID de la cola */
	{
		sprintf(mensaje, "Error al obtener el ID de la cola Externa\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		exit(-1);
	}
	
	if ( (colaI = msgget(clave_colaI, 0666)) < 0 )				/* Obtengo el ID de la cola */
	{
		sprintf(mensaje, "Error al obtener el ID de la cola Interna\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		exit(-1);
	}

	/* Defino el stock a pie de maquina */
	stock_caja.stock = 12;							/* Cantidad de stock que puedo almacenar */
	stock_caja.stockMinimo = 3;
	stock_caja.stockLibre = rand()%stock_caja.stock + 1;
	stock_caja.estado = 0;							/* 0 sin Kanban Proveedor, 1 con Kanban Proveedor */		

	/* Armo el Kanban de Proveedor, para solicitar stock */
	msg_kproveedor.sector=getpid();
	msg_kproveedor.mtype = MSG_PROVEEDOR;
	msg_kproveedor.tugger=0;
	msg_kproveedor.darsena=0;
	msg_kproveedor.cantidadEntregada=0;
	msg_kproveedor.fechaEntrega=0;
	msg_kproveedor.horaEntrega=0;
	msg_kproveedor.entregada=0;

	/* Armo la copia del Kanban de Proveedor para la Oficina de Compras */
	msg_kcompras.sector = getpid();
	msg_kcompras.mtype = MSG_OCOMPRAS;
	msg_kcompras.tugger = 0;
	msg_kcompras.darsena = 0;
	msg_kcompras.cantidadEntregada = 0;
	msg_kcompras.fechaEntrega = 0;
	msg_kcompras.horaEntrega = 0;
	msg_kcompras.entregada = 0;


	printf("+---------------------------+\n");
	printf("| Stock libre inicial: %d\n", stock_caja.stockLibre);
	printf("| Stock total: %d\n", stock_caja.stock);
	printf("+---------------------------+\n");
	printf("\n");

	while(1)
	{
		/* Espero Kanban de produccion con las cantidades a producir */
		if ( msgrcv(colaI, (m_kanbanproduccion *) &msg_kproduccion, sizeof(m_kanbanproduccion), MSG_CAJA_PROD, 0) < 0 )
		{
			sprintf(mensaje, "Caja: Error al recibir el pedido de Armado KProduccion\n");
			write(fileno(stdout), mensaje, strlen(mensaje));
			exit(-1);
		}

		printf("+------------------------------------+\n");
		printf("| Caja: Recibi KProduccion de Armado |\n");
		printf("+------------------------------------+\n");
		printf("Sector: %d\n", msg_kproduccion.sector);
		printf("Cantidad de cajas a producir: %d\n", msg_kproduccion.cantVehiculos);
		printf("\n");

		/* Se produce la misma cantidad de cajas que de autos */
		fentregar = msg_kproduccion.cantVehiculos;

		for (producidos=1; producidos <= fentregar; producidos++)
		{		
			if ( msgrcv(colaI, (m_kanbanentreprocesos *) &msg_kprocesos, sizeof(m_kanbanentreprocesos), MSG_CAJA_PROC, 0) < 0 )
			{
				sprintf(mensaje, "Caja: Error al recibir EProcesos de Armado\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				exit(-1);
			}

			printf("+----------------------------------------------+\n");
			printf("| Caja: Recibi de Armado Kanban entre procesos |\n");
			printf("+----------------------------------------------+\n");
			printf("Sector: %ld\n", msg_kprocesos.nroSector);
			printf("nroVehiculo: %ld\n", msg_kprocesos.nroVehiculo);
			printf("codParte: %ld\n", msg_kprocesos.codParte);
			printf("nroOrden: %ld\n", msg_kprocesos.nroOrden);
			printf("\n");

			/*
				Verifico la cantidad de stock, si esta por debajo del minimo hago un pedido.
				Verifico tambien si el pedido ya esta hecho o no
			*/
			if ((stock_caja.stockMinimo >= stock_caja.stock - stock_caja.stockLibre) && (stock_caja.estado == 0))
			{
				msg_kproveedor.cantidad = stock_caja.stock - stock_caja.stockMinimo;

				printf("+----------------------------------+\n");
				printf("| Caja: Solicito Stock a Proveedor |\n");
				printf("+----------------------------------+\n");
				printf("Nivel de stock: %d\n", stock_caja.stock - stock_caja.stockLibre);
				printf("Solicito a proveedor: %d\n", msg_kproveedor.cantidad);
				printf("\n");

				/* Marco el estado del Stock como que ya emiti un Kanban al Proveedor (para no repetir el pedido ) */
				stock_caja.estado = 1;

				if ( msgsnd(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), 0) < 0 )
				{
					sprintf(mensaje, "Caja: Error al enviar a Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}

				msg_kcompras.cantidad = msg_kproveedor.cantidad;

				/* Mando copia del Kanban de Proveedores a la Oficina de Compras */
				if ( msgsnd(colaE, (m_kanbancompras *) &msg_kcompras, sizeof(m_kanbancompras), 0) < 0 )
				{
					sprintf(mensaje, "Caja: Error al enviar a Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}
			}

			/* Verifico si el Proveedor ya me entrego el stock que habia solicitado */
			if ( temprcv = msgrcv(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), getpid(), IPC_NOWAIT) != -1 )
			{
				stock_caja.stockLibre = stock_caja.stockLibre - msg_kproveedor.cantidadEntregada;
				stock_caja.estado = 0;

				printf("+---------------------------------+\n");
				printf("| Caja: Recibi Stock de Proveedor |\n");
				printf("+---------------------------------+\n");
				printf("Cantidad de piezas: %d\n", msg_kproveedor.cantidad);
				printf("\n");
			}
			if ( temprcv < 0 )
			{
				sprintf(mensaje, "Caja: Error al recibir KanbanProveedores\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				exit(-1);
			}

			/* Si llego al nivel cero de stock, me quedo frenando esperando que el Proveedor me conteste */
			if ((stock_caja.stockLibre == stock_caja.stock) && (stock_caja.estado == 1))
			{
				sprintf(mensaje, "Caja: No tengo stock, me bloqueo en espera\n\n");
				write(fileno(stdout), mensaje, strlen(mensaje));

				if ( msgrcv(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), getpid(), 0) < 0 )
				{
					sprintf(mensaje, "Caja: Error al recibir KProv de Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}
				stock_caja.estado = 0;
			}

			//modifico KanbanEntreProcesos y Produccion
			/* Comienzo el proceso de Produccion */
			stock_caja.stockLibre++;
			sprintf(mensaje, "Caja: Armando Caja %d de %d...\n", producidos, fentregar);
			write(fileno(stdout), mensaje, strlen(mensaje));
			sleep(rand()%5);
			sprintf(mensaje, "Caja: Stock disponible: %d \n\n", stock_caja.stock - stock_caja.stockLibre);
			write(fileno(stdout), mensaje, strlen(mensaje));

			msg_kprocesos.mtype = MSG_ARMADO_CAJA;

			sprintf(mensaje, "Caja: Envio KanbanEntreProcesos a %d\n\n", msg_kprocesos.nroSector);
			write(fileno(stdout), mensaje, strlen(mensaje));

			if ( msgsnd(colaI, (m_kanbanentreprocesos *) &msg_kprocesos, sizeof(m_kanbanentreprocesos), 0) < 0 )
			{
				sprintf(mensaje, "Caja: Error al encolar kprocesos nro %d\n", msg_kprocesos.nroVehiculo);
				write(fileno(stdout), mensaje, strlen(mensaje));

		        	exit(-1);
			}
		}

		sprintf(mensaje, "Caja: Espero nuevo Kanban de Produccion\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
	}
}
